着色器程序(Shader)的最终目的就是确定图形的顶点(Vertex)坐标和片元(Fragment)颜色。其实这正是 OpenGL 提供的最基本、最核心的操作原语,我们想要用 OpenGL 实现任何效果,无论是静止的光影、色彩、形状,还是运动的物理效果、粒子效果,归根结底都是要根据时间和位置确定顶点坐标和片元颜色。
常用 2D 纹理变换,其核心思想就是调整纹理坐标和顶点坐标 。
处理框架:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public void setTransformation (final Transformation transformation) { if (transformation.cropRect != null ) { resolveCrop(transformation.cropRect.left, transformation.cropRect.top, transformation.cropRect.right - transformation.cropRect.left, transformation.cropRect.bottom - transformation.cropRect.top); } if (transformation.flip != 0 ) { resolveFlip(transformation.flip); } if (transformation.rotation != 0 ) { resolveRotate(transformation.rotation); } if (transformation.inputSize != null && transformation.outputSize != null ) { resolveScale(transformation.inputSize.right - transformation.inputSize.left, transformation.inputSize.bottom - transformation.inputSize.top, transformation.outputSize.right - transformation.outputSize.left, transformation.outputSize.bottom - transformation.outputSize.top, transformation.scaleType); } }
裁剪
裁剪实际上是修改TEX_VERTEX的坐标值
1 2 3 4 5 6 private final float [] TEX_VERTEX = { 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , };
修改的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private void resolveCrop (float x, float y, float width, float height) { float minX = x; float minY = y; float maxX = minX + width; float maxY = minY + height; TEX_VERTEX[0 ] = minX; TEX_VERTEX[1 ] = minY; TEX_VERTEX[2 ] = maxX; TEX_VERTEX[3 ] = minY; TEX_VERTEX[4 ] = minX; TEX_VERTEX[5 ] = maxY; TEX_VERTEX[6 ] = maxX; TEX_VERTEX[7 ] = maxY; }
调用方法:
1 2 3 4 5 6 7 8 9 10 11 12 public GlRender () { Transformation transformation = new Transformation(); RectF rect = new RectF(0.8f , 0 , 1f , 1 ); transformation.cropRect = rect; setTransformation(transformation); mBuffer = Util.getFloatBuffer(VERTEX); mTexVertexBuffer = Util.getFloatBuffer(TEX_VERTEX); mVertexIndexBuffer = Util.getShortBuffer(VERTEX_INDEX); }
翻转
翻转跟裁剪一样,也是修改TEX_VERTEX数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private void resolveFlip (int flip) { switch (flip) { case Transformation.FLIP_HORIZONTAL: swap(TEX_VERTEX, 0 , 2 ); swap(TEX_VERTEX, 4 , 6 ); break ; case Transformation.FLIP_VERTICAL: swap(TEX_VERTEX, 1 , 5 ); swap(TEX_VERTEX, 3 , 7 ); break ; case Transformation.FLIP_HORIZONTAL_VERTICAL: swap(TEX_VERTEX, 0 , 2 ); swap(TEX_VERTEX, 4 , 6 ); swap(TEX_VERTEX, 1 , 5 ); swap(TEX_VERTEX, 3 , 7 ); break ; case Transformation.FLIP_NONE: default : break ; } }
1 2 3 Transformation transformation = new Transformation(); transformation.flip = Transformation.FLIP_VERTICAL; setTransformation(transformation);
旋转
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 private void resolveRotate (int rotation) { switch (rotation) { case Transformation.ROTATION_90: swap(TEX_VERTEX, 1 , 5 ); swap(TEX_VERTEX, 2 , 6 ); break ; case Transformation.ROTATION_180: swap(TEX_VERTEX, 0 , 4 ); swap(TEX_VERTEX, 1 , 5 ); swap(TEX_VERTEX, 2 , 6 ); swap(TEX_VERTEX, 3 , 7 ); break ; case Transformation.ROTATION_270: swap(TEX_VERTEX, 0 , 4 ); swap(TEX_VERTEX, 3 , 7 ); break ; case Transformation.ROTATION_0: default : break ; } }
1 2 3 Transformation transformation = new Transformation(); transformation.rotation = Transformation.ROTATION_270; setTransformation(transformation);
缩放
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 private void resolveScale (int inputWidth, int inputHeight, int outputWidth, int outputHeight, int scaleType) { if (scaleType == Transformation.SCALE_TYPE_FIT_XY) { return ; } if (inputWidth * outputHeight == inputHeight * outputWidth) { return ; } float inputAspect = inputWidth / (float ) inputHeight; float outputAspect = outputWidth / (float ) outputHeight; if (scaleType == Transformation.SCALE_TYPE_CENTER_CROP) { if (inputAspect < outputAspect) { float heightRatio = outputAspect / inputAspect; VERTEX[1 ] *= heightRatio; VERTEX[4 ] *= heightRatio; VERTEX[7 ] *= heightRatio; VERTEX[10 ] *= heightRatio; } else { float widthRatio = inputAspect / outputAspect; VERTEX[0 ] *= widthRatio; VERTEX[3 ] *= widthRatio; VERTEX[6 ] *= widthRatio; VERTEX[9 ] *= widthRatio; } } else if (scaleType == Transformation.SCALE_TYPE_CENTER_INSIDE) { if (inputAspect < outputAspect) { float widthRatio = inputAspect / outputAspect; VERTEX[0 ] *= widthRatio; VERTEX[3 ] *= widthRatio; VERTEX[6 ] *= widthRatio; VERTEX[9 ] *= widthRatio; } else { float heightRatio = outputAspect / inputAspect; VERTEX[1 ] *= heightRatio; VERTEX[4 ] *= heightRatio; VERTEX[7 ] *= heightRatio; VERTEX[10 ] *= heightRatio; } } }
1 2 3 4 5 6 Rect rect = new Rect(0 , 0 , 1 , 1 ); transformation.inputSize = rect; Rect rect2 = new Rect(0 , 0 , 1 , 2 ); transformation.outputSize = rect2; transformation.scaleType = Transformation.SCALE_TYPE_CENTER_CROP; setTransformation(transformation);
缩放修改的是VERTEX。